package cn.edu.hnu.gpg.service;

import cn.edu.hnu.gpg.dao.TeacherMapper;
import cn.edu.hnu.gpg.dto.Account;
import cn.edu.hnu.gpg.entity.*;
import cn.edu.hnu.gpg.entity.enums.AcademicDegree;
import cn.edu.hnu.gpg.entity.enums.AcademicTitle;
import cn.edu.hnu.gpg.entity.enums.Gender;
import cn.edu.hnu.gpg.entity.enums.UserType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class TeacherServiceImpl implements TeacherService {

    private static final Logger logger = LogManager.getLogger(TeacherService.class);

    @Autowired
    private UserService userService;

    private TeacherMapper teacherMapper;

    @Autowired
    public TeacherServiceImpl(TeacherMapper teacherMapper){
        this.teacherMapper = teacherMapper;
    }

    @Override
    public Teacher findTeacherByTeacherNo(String teacher_no) {
        if (teacher_no.isEmpty())
            return null;
        TeacherExample teacherExample = new TeacherExample();
        teacherExample.or().andTeacherNumberEqualTo(teacher_no);
        List<Teacher> teachers = teacherMapper.selectByExample(teacherExample);
        return teachers.size()>0 ? teachers.get(0) : null;
    }

    @Override
    public Teacher findTeacherByUserId(int user_id) {
        if(user_id<=0)
            return null;

        TeacherExample teacherExample = new TeacherExample();
        teacherExample.or().andUserIdEqualTo(user_id);
        List<Teacher> teachers = teacherMapper.selectByExample(teacherExample);
        return teachers.size()>0 ? teachers.get(0) : null;
    }

    @Override
    public Teacher findTeacherByTeacherId(int teacher_id) {
        if (teacher_id < 1)
            return null;

        return teacherMapper.selectByPrimaryKey(teacher_id);
    }

    @Override
    public List<Teacher> findTeacherLike(Teacher teacher) {

        TeacherExample example = new TeacherExample();

        if (teacher.getTeacherNumber() != null && !teacher.getTeacherNumber().isEmpty())
            example.or().andTeacherNumberLike(teacher.getTeacherNumber() + "%");
        if (teacher.getIdNumber() != null && !teacher.getIdNumber().isEmpty())
            example.or().andIdNumberLike(teacher.getIdNumber() + "%");
        if (teacher.getName() != null && !teacher.getName().isEmpty())
            example.or().andNameLike(teacher.getName() + "%");

        return teacherMapper.selectByExample(example);
    }

    @Override
    public List<Account> findTeacherAccount(Teacher teacher, boolean onlyActiveAccount) {
        List<Account> accountList;

        try {
            List<Teacher> teacherList = findTeacherLike(teacher);
            accountList = new ArrayList<>(teacherList.size());

            for (Teacher t : teacherList) {
                User user = userService.findUserByUsername(t.getTeacherNumber());

                if (user == null)
                    continue;

                if (onlyActiveAccount && !user.getActive()) {
                    continue;
                }

                Account account = new Account(t);
                account.setUser(user);
                accountList.add(account);
            }

            return accountList;
        } catch (Exception e) {
            logger.debug(e);
            return null;
        }
    }

    @Override
    public int createTeacher(int user_id, String teacher_number, String id_number, String name, Gender gender, @Nullable Date birth_date, @Nullable String phone, short department_id, AcademicTitle academic_title, AcademicDegree highest_degree) {
        if(user_id<=0)
            return 0;

        if(teacher_number.isEmpty())
            throw new IllegalArgumentException("teacher_number is empty");

        if(id_number.isEmpty())
            throw new IllegalArgumentException("id_number is empty");

        if (name.isEmpty())
            throw new IllegalArgumentException("name is empty");

        if(gender == null)
            throw new IllegalArgumentException("gender is null");

        if (academic_title == null)
            throw new IllegalArgumentException("academic_title is null");

        if (highest_degree == null)
            throw new IllegalArgumentException("highest_degree is null");

        Teacher teacher = new Teacher();
        teacher.setUserId(user_id);
        teacher.setTeacherNumber(teacher_number);
        teacher.setIdNumber(id_number);
        teacher.setName(name);
        teacher.setGender(gender);
        teacher.setBirthDate(birth_date);
        teacher.setPhone(phone);
        teacher.setDepartmentId(department_id);
        teacher.setHighestDegree(highest_degree);
        teacher.setAcademicTitle(academic_title);

        int id = teacherMapper.insertSelective(teacher);
        if (id == 1)
            return teacher.getTeacherId();
        else return id;
    }

    @Override
    public int createTeacherAccount(String teacher_number, String id_number, String name, Gender gender, @Nullable Date birth_date, @Nullable String phone, short department_id, AcademicTitle academic_title, AcademicDegree highest_degree) {
        //注册用户时，使用教师的teacher_number,id_number分别做为用户名和密码，可确保数据的唯一性，亦方便教师记忆
        int user_id = userService.createUser(teacher_number,id_number,UserType.T);

        //创建教师
        int id = createTeacher(user_id, teacher_number, id_number, name,gender, birth_date, phone, department_id, academic_title, highest_degree);

        return id;
    }

    @Override
    public int createTeacherAccount(Teacher teacher) {

        if (teacher == null)
            throw new IllegalArgumentException("teacher is null");

        int userId = userService.createUser(teacher.getTeacherNumber(), teacher.getIdNumber().substring(12), UserType.T);
        teacher.setUserId(userId);
        teacherMapper.insertSelective(teacher);

        return teacher.getTeacherId();
    }

    @Override
    public boolean updateInfo(int user_id, String teacher_number, String id_number, String name, Gender gender, @Nullable Date birth_date, @Nullable String phone, short department_id, AcademicTitle academic_title, AcademicDegree highest_degree) {
        //user_id无效的话，直接返回false
        if(user_id<=0)
            return false;

        if(teacher_number.isEmpty())
            throw new IllegalArgumentException("teacher_number is empty");

        if(id_number.isEmpty())
            throw new IllegalArgumentException("id_number is empty");

        if (name.isEmpty())
            throw new IllegalArgumentException("name is empty");

        if(gender == null)
            throw new IllegalArgumentException("gender is null");

        if (academic_title == null)
            throw new IllegalArgumentException("academic_title is null");

        if (highest_degree == null)
            throw new IllegalArgumentException("highest_degree is null");

        //通过user_id获取对应的teacher对象
        Teacher teacher = findTeacherByUserId(user_id);

        //若有修改的数据，通过下面的操作可确保将需要修改的属性列更新
        teacher.setTeacherNumber(teacher_number);
        teacher.setIdNumber(id_number);
        teacher.setName(name);
        teacher.setGender(gender);
        teacher.setBirthDate(birth_date);
        teacher.setPhone(phone);
        teacher.setDepartmentId(department_id);
        teacher.setHighestDegree(highest_degree);
        teacher.setAcademicTitle(academic_title);

        return teacherMapper.updateByPrimaryKey(teacher) >= 1;
    }

    @Override
    public boolean updateTeacherByTeacherNumber(Teacher teacher, boolean skipNull) {
        if (teacher.getTeacherNumber() == null)
            throw new RuntimeException("Student number is null");

        TeacherExample example = new TeacherExample();
        example.or().andTeacherNumberEqualTo(teacher.getTeacherNumber());

        int successLines;
        if (skipNull) {
            successLines = teacherMapper.updateByExampleSelective(teacher, example);
        } else {
            successLines = teacherMapper.updateByExample(teacher, example);
        }

        return successLines >= 1;
    }
}
